#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Calculator.hpp"
#include "Daemon.hpp"

using namespace TcpServerArea;

using cal_func_t = std::function<Response(const Request &req)>;

class Parse
{
public:
    Parse(cal_func_t cal_func) : _cal_func(cal_func)
    {
    }

    // 获取的是序列化的message
    std::string Entry(std::string &package)
    {
        // 判断报文完整性len\r\n{json}\r\n
        std::string message;
        std::string result;

        // 将 {json} 解包出来
        while (Decode(package, &message))
        {
            if (message.empty())
                break;

            // 反序列化,拿到 x,y,oper
            Request req;
            if (!req.Deserialize(message))
                break;

            std::cout << "#############" << std::endl;
            req.Print();
            std::cout << "#############" << std::endl;

            // Calculator cal;
            // Response res = cal.Excute(req);

            // 计算结果:将计算函数作分层,使用回调函数
            Response res = _cal_func(req);

            // 序列化
            std::string temp;
            res.Serialize(temp); // 将计算结果序列化为 {json}
            LOG(LogLevel::DEBUG) << "序列化: \n"
                                 << temp;

            // 封装为 len\r\n{json}\r\n
            Encode(temp);
            LOG(LogLevel::DEBUG) << "添加len报头: \n"
                                 << temp;

            result += temp;
        }

        LOG(LogLevel::DEBUG) << "result: \n"
                             << result;
        return result;
    }

private:
    cal_func_t _cal_func;
};

int main()
{
    // USE_CONSOLE_STRATEGY();
    USE_FILE_STRATEGY();
    

    // std::shared_ptr<Command> cmd_ptr = std::make_shared<Command>();

    // std::shared_ptr<TcpServer> tcp_ptr = std::make_shared<TcpServer>([&cmd_ptr](std::string cmd_str){
    //     return cmd_ptr->Execute(cmd_str);
    // });

    Daemon(false,false);

    std::shared_ptr<Calculator> cal_ptr = std::make_shared<Calculator>();

    std::shared_ptr<Parse> par_ptr = std::make_shared<Parse>([&cal_ptr](const Request &req)
                                                             { return cal_ptr->Excute(req); });

    std::shared_ptr<TcpServer> tcp_ptr = std::make_shared<TcpServer>([&par_ptr](std::string &package)
                                                                     { return par_ptr->Entry(package); });

    tcp_ptr->InitServer();

    tcp_ptr->Start();
    return 0;
}